MCU 内部FLASH+FATFS文件系统+U盘

大概搞好了stm32的usb device之后,开始搞fatfs文件系统,
大概了解一下fatfs文件系统的结构和移植需要修改的地方之后,
打算仍旧使用内部flash作存储空间,加上之前做的u盘,就可以用fatfs通过串口操作发送命令,新建,删除,读写文件,然后插上usb通过电脑反映出来 。
同时也可以在 电脑上操作文件,然后通过fatfs用串口读出来验证。
试验中为了方便调试,使用了正点原子的USMART调试组件。
参考网上关于fatfs文件系统移植 的设置,修改disk_io.c,其中的存储器操作函数和usb中一样都是用内部flash的操作函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#define     FLASH_START_ADDR        0x0803fc00   // Flash start address 
#define FLASH_SIZE 0x40000 // 256K
#define FLASH_BLOCK_SIZE 0x800 // 2k Bytes per page
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to read (1..128) */
)

{

DRESULT res;
int result;

switch (pdrv) {
case Em_Flash :
for(;count>0;count--)
{
STMFLASH_Read(FLASH_START_ADDR + sector*2048,(u16*)buff,1024);
SPI_Flash_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
sector++;
buff+=2048;
}
return RES_OK;
}
return RES_PARERR;
}
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to write (1..128) */
)

{

switch (pdrv) {
case Em_Flash :
for(;count>0;count--)
{
STMFLASH_Write(FLASH_START_ADDR + sector*2048,(u16*)buff,1024);
sector++;
buff+=2048;
}
return RES_OK;
}
return RES_PARERR;
}
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)

{

DRESULT res;
if(drv==Em_Flash)//SD¿¨
{
switch(ctrl)
{
case CTRL_SYNC:
res = RES_OK;

break;
case GET_SECTOR_SIZE:
*(WORD*)buff = 2048;
res = RES_OK;
break;
case GET_BLOCK_SIZE:
*(WORD*)buff = 1;
res = RES_OK;
break;
case GET_SECTOR_COUNT:
*(DWORD*)buff =128;
res = RES_OK;
break;
default:
res = RES_PARERR;
break;
}
}

else res=RES_ERROR;
return res;
}

为了支持长文件名,参考正点原子的fatfs例子,使用了malloc,动态内存管理文件。
也使用了正点原子的测试文件fattester和extfun文件。
做好之后,就可以使用串口调试助手用fatfs文件系统操作文件了。
同时可以通过usb从上位机反映出来,因为用的都是同一块flash存储空间。

一开始,我是参考正点原子的例子,设置flash的 sector size为512bytes,blocksize=sectorsize*4.并 在ffconf.h中设置MAX_SS为512.
disk_io中的函数也都是以512字节为一个sector来操作的。
固件做好了后,发现上位机可以正常使用小u盘,但是用串口调试时 ,fatfs总是返回没有文件系统的错误,
而用fatfs的格式化函数个时候之后,可以正常用fatfs操作,但是再次连接电脑,电脑提示需要格式化。
也就是说电脑的格式化和fatfs的格式化不兼容。这是什么问题呢?

后来使用stlink+stvp软件查看flash,发现电脑将flash格式化成fat12格式了,并不是fat32格式,
原来fat32不支持500MB以下的存储设备。查看引导扇区的数据,第11个偏移地址0800,也就是2048,扇区大小为2048。
跟踪fatfs源码,因为设置MAX_SS为512,fatfs会判断2048!=512.
也就是说扇区分配字节数不一致,就返回NO_FILESYSTEM的错误。
之后将MAX_SS设置为2048并将disk_io中的函数改为以2048为一个sector来操作。
这样就完全正常了。fatfs和电脑的文件系统可以相互识别。